package com.jic.member.impl;


import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.ImmutableMap;
import com.jic.common.utils.HttpClientUtils;
import com.jic.member.constant.enums.MessageTypeEnum;
import com.jic.member.constant.enums.NodeTemplateTypeEnum;
import com.jic.member.mapper.TripBranchNodeEntityMapper;
import com.jic.member.mapper.TripExecuteInfoEntityMapper;
import com.jic.member.entity.TSmsTouchSettings;
import com.jic.member.entity.TripBranchNodeEntity;
import com.jic.member.entity.TripExecuteInfoEntity;
import com.jic.member.entity.TripPeopleEntity;
import com.jic.member.request.TestSendMessageRequest;
import com.jic.member.response.MessageResponse;
import com.jic.member.response.UserSendSmsCountResponse;
import com.jic.member.service.MememberUserService;
import com.jic.member.service.MessageService;
import com.jic.member.service.TSmsTouchSettingsService;
import com.jic.member.service.TripTimingJobService;
import com.jic.member.response.MememberUserResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


/**
 * 消息发送业务处理
 * @author : 
 * @email : 
 * @since : 2020-06-08 11:03:19
 * @version : v1.0.0
 */
@Slf4j
@Service("messageService")
@RefreshScope
public class MessageServiceImpl implements MessageService {

    @Value("${message.mail.url}")
    private String mailUrl;

    @Value("${message.sms.url}")
    private String smsUrl;


    @Value("${message.accessKey}")
    private String accessKey;

    /**
     * 消息中心发送成功 返回CODE
     */
    private static final String SUCCESS_CODE = "0";

    /**
     * 短信触达时间限制类型
     */
    private static final int TIME_LIMIT_DAY = 1;

    private static final int TIME_LIMIT_WEEK = 2;

    private static final int TIME_LIMIT_MONTH = 3;

    @Autowired
    private MememberUserService mememberUserService;

    @Autowired
    private TripBranchNodeEntityMapper tripBranchNodeEntityMapper;

    @Autowired
    private TripExecuteInfoEntityMapper tripExecuteInfoEntityMapper;

    @Autowired
    private TripTimingJobService tripTimingJobService;

    @Autowired
    private TSmsTouchSettingsService tSmsTouchSettingsService;



    /**
     * 触达方式-邮件、短信测试发送
     * @param testSendMessageRequest
     * @return
     */
    @Override
    public MessageResponse sendTestMessage(TestSendMessageRequest testSendMessageRequest){
        MessageResponse response = new MessageResponse();
        JSONObject params = new JSONObject();
        params.put("params", testSendMessageRequest.getParams());
        params.put("receiver",testSendMessageRequest.getTestReceiver());
        params.put("tempId",testSendMessageRequest.getTempId());
        params.put("accessKey",accessKey);
        log.info("发送短信, testSendSmsMailRequest: {}", JSONArray.toJSONString(params));
        HttpClientUtils.setHeader(new HashMap<String, String>(2){{
            put("Content-Type","application/json;charset=UTF-8");
        }});
        String url = null;
        if(MessageTypeEnum.MAIL_SEND.getCode().equals(testSendMessageRequest.getType())){
            url = mailUrl;
            params.put("mailTitle",testSendMessageRequest.getMailTitle());
        }else if(MessageTypeEnum.SMS_SEND.getCode().equals(testSendMessageRequest.getType())){
            url = smsUrl;
        }
        String result = HttpClientUtils.doPostJson(url, params);
        log.info("调用结果, rest：{}",result);
        if(StringUtils.isNotEmpty(result)){
            String code = JSONArray.parseObject(result, Map.class).get("code").toString();
            String message = JSONArray.parseObject(result, Map.class).get("message").toString();
            if(SUCCESS_CODE.equals(code)){
                log.info("调用成功, rest：{}",result);
                response.setCode(code);
                response.setMessage(message);
                return response;
            }else{
                log.error("调用失败,result："+result);
                response.setCode(code);
                response.setMessage(message);
                return response;
            }
        }else{
            log.error("调用失败,result：null");
            response.setCode("-1");
            response.setMessage("调用发送失败");
            return response;
        }
    }


    /**
     * 执行动作-发送邮件
     * @param branchNodeId 分支节点ID
     * @return
     */
    @Override
    public Boolean branchNodeBySendMail(Long tripId, Long branchNodeId, List<String> userIds){

        Boolean flag = false;
        Map messageResult = new HashMap();//发送结果集
        TripPeopleEntity tripPeopleEntity = new TripPeopleEntity();
        tripPeopleEntity.setBranchNodeId(branchNodeId);
        List<MememberUserResponse>  userList = mememberUserService.queryByThirdUserIds(StringUtils.join(userIds,","));
        TripBranchNodeEntity tripBranchNodeEntity = tripBranchNodeEntityMapper.queryById(branchNodeId);
        JSONObject params = new JSONObject();
        JSONObject map = JSONObject.parseObject(tripBranchNodeEntity.getNodeVariable());
        List<String> receiver = new ArrayList<>();
        List<MememberUserResponse> sendUserList = new ArrayList<>();
        for(MememberUserResponse response : userList){
            if(StringUtils.isNotEmpty(response.getEmail())){
                sendUserList.add(response);
                receiver.add(response.getEmail());
            }
        }
        if(sendUserList.size() > 0){
            params.put("params", map.get("params"));
            params.put("receiver",StringUtils.join(receiver,","));
            //TODO  邮件标题等卡奥斯接口文档 决定是否更改KEY
            params.put("mailTitle",map.get("mailTitle"));
            params.put("tempId",map.get("tempId"));
            params.put("accessKey",accessKey);

            log.info("发送邮件, testSendSmsMailRequest: {}", JSONArray.toJSONString(params));
            HttpClientUtils.setHeader(new HashMap<String, String>(2){{
                put("Content-Type","application/json;charset=UTF-8");
            }});
            String result = HttpClientUtils.doPostJson(mailUrl, params);
            messageResult.put("result", result);
            messageResult.put("receiverMail", receiver);
            log.info("调用结果, rest：{}",result);
            if(StringUtils.isNotEmpty(result)){
                String code = JSONArray.parseObject(result, Map.class).get("code").toString();
                if(SUCCESS_CODE.equals(code)){
                    flag = true;
                }else{
                    log.error("调用失败,result："+result);
                    flag = false;
                }
            }else{
                log.error("调用失败,result：null");
                flag = false;
            }

            JSONObject reqVariable = new JSONObject();
            reqVariable.put("tripId",tripId);
            reqVariable.put("branchNodeId",branchNodeId);
            reqVariable.put("userIds",userIds);
            List<TripExecuteInfoEntity> tripExecuteInfoEntityList = new ArrayList<>();
            for(String userId : userIds){
                Boolean finalFlag = flag;
                TripExecuteInfoEntity tripExecuteInfoEntity = new TripExecuteInfoEntity(){{
                    setThirdUserId(userId);
                    setBranchId(tripBranchNodeEntity.getBranchId());
                    setTripId(tripId);
                    setBranchNodeId(branchNodeId);
                    setNodeTemplateCode(tripBranchNodeEntity.getNodeTemplateCode());
                    setRequestVariable(reqVariable.toString());
                    setResponseVariable(messageResult.toString());
                    setStatus(finalFlag == true ? 1 : 2);
                    setType(2);
                    setDeptId(tripBranchNodeEntity.getDeptId());
                    setDeptType(tripBranchNodeEntity.getDeptType());

                }};
                tripExecuteInfoEntityList.add(tripExecuteInfoEntity);
            }
            if(userIds.size() > 0){
                tripExecuteInfoEntityMapper.foreachInsert(tripExecuteInfoEntityList);
            }
        }

        // 下一个节点
        tripTimingJobService.exeNext(branchNodeId, userIds);
        return flag;
    }



    /**
     * 执行动作-发送短信
     * @param branchNodeId 分支节点ID
     * @return
     */
    @Override
    public Boolean branchNodeBySendSms(Long tripId, Long branchNodeId, List<String> userIds){
        Boolean flag = false;
        Map messageResult = new HashMap();//发送结果集
        TripPeopleEntity tripPeopleEntity = new TripPeopleEntity();
        tripPeopleEntity.setBranchNodeId(branchNodeId);
        List<Long > checkUserIds =  checkUserSendSmsCount(userIds);
        List<MememberUserResponse>  userList = mememberUserService.queryByThirdUserIds(StringUtils.join(checkUserIds,","));
        TripBranchNodeEntity tripBranchNodeEntity = tripBranchNodeEntityMapper.queryById(branchNodeId);
        JSONObject params = new JSONObject();
        JSONObject map = JSONObject.parseObject(tripBranchNodeEntity.getNodeVariable());
        List<String> receiver = new ArrayList<>();
        List<MememberUserResponse> sendUserList = new ArrayList<>();
        for(MememberUserResponse response : userList){
            if(StringUtils.isNotEmpty(response.getPhone())){
                receiver.add(response.getPhone());
                sendUserList.add(response);
            }
        }

        if(sendUserList.size() > 0){
            params.put("params", map.get("params"));
            params.put("receiver",StringUtils.join(receiver,","));
            params.put("tempId",map.get("tempId"));
            params.put("accessKey",accessKey);

            log.info("发送邮件, testSendSmsMailRequest: {}", JSONArray.toJSONString(params));
            HttpClientUtils.setHeader(new HashMap<String, String>(2){{
                put("Content-Type","application/json;charset=UTF-8");
            }});
            String result = HttpClientUtils.doPostJson(smsUrl, params);
            messageResult.put("result", result);
            messageResult.put("receiverSms", receiver);
            log.info("调用结果, rest：{}",result);
            if(StringUtils.isNotEmpty(result)){
                String code = JSONArray.parseObject(result, Map.class).get("code").toString();
                if(SUCCESS_CODE.equals(code)){
                    flag = true;
                }else{
                    log.error("调用失败,result："+result);
                    flag = false;
                }
            }else{
                log.error("调用失败,result：null");
                flag = false;
            }
            JSONObject reqVariable = new JSONObject();
            reqVariable.put("tripId",tripId);
            reqVariable.put("branchNodeId",branchNodeId);
            reqVariable.put("userIds",userIds);
            List<TripExecuteInfoEntity> tripExecuteInfoEntityList = new ArrayList<>();
            for(String userId : userIds){
                Boolean finalFlag = flag;
                TripExecuteInfoEntity tripExecuteInfoEntity = new TripExecuteInfoEntity(){{
                    setThirdUserId(userId);
                    setBranchId(tripBranchNodeEntity.getBranchId());
                    setTripId(tripId);
                    setBranchNodeId(branchNodeId);
                    setNodeTemplateCode(tripBranchNodeEntity.getNodeTemplateCode());
                    setRequestVariable(reqVariable.toString());
                    setResponseVariable(messageResult.toString());
                    setStatus(finalFlag == true ? 1 : 2);
                    setType(2);
                    setDeptId(tripBranchNodeEntity.getDeptId());
                    setDeptType(tripBranchNodeEntity.getDeptType());

                }};
                tripExecuteInfoEntityList.add(tripExecuteInfoEntity);
            }
            if(userIds.size() > 0){
                tripExecuteInfoEntityMapper.foreachInsert(tripExecuteInfoEntityList);
            }
        }

        // 下一个节点
        tripTimingJobService.exeNext(branchNodeId, userIds);
        return flag;
    }



    /**
     * 触达方式（发送消息）- 短信、邮件、AppPush、公众号
     * 发放优惠券、红包、推送活动、商品后续动作
     * @param tripId
     * @param branchNodeId
     * @param userIds
     * @return
     */
    @Override
    public Boolean branchNodeBySendMessage(Long tripId, Long branchNodeId, List<String> userIds){
        Boolean flag = false;
        Map messageResult = new HashMap();//发送结果集
        TripPeopleEntity tripPeopleEntity = new TripPeopleEntity();
        tripPeopleEntity.setBranchNodeId(branchNodeId);
        List<MememberUserResponse>  userList = mememberUserService.queryByThirdUserIds(StringUtils.join(userIds,","));
        TripBranchNodeEntity tripBranchNodeEntity = tripBranchNodeEntityMapper.queryById(branchNodeId);
        JSONObject map = JSONObject.parseObject(tripBranchNodeEntity.getNodeVariable());
        //触达人数 初始化
        List<String> receiverSms = new ArrayList<>();
        List<MememberUserResponse> sendSmsUserList = new ArrayList<>();
        List<String> receiverMail = new ArrayList<>();
        List<MememberUserResponse> sendMailUserList = new ArrayList<>();
        for(MememberUserResponse response : userList){
            //判断是否存在手机号、邮箱
            if(StringUtils.isNotEmpty(response.getPhone())){
                receiverSms.add(response.getPhone());
                sendSmsUserList.add(response);
            }
            if(StringUtils.isNotEmpty(response.getEmail())){
                receiverMail.add(response.getEmail());
                sendMailUserList.add(response);
            }
        }


        List<Long > checkUserIds =  checkUserSendSmsCount(userIds);
        receiverSms = userList.stream().filter(x->{return (checkUserIds.contains(x.getThirdUserId()) && StringUtils.isNotEmpty(x.getPhone()));})
                .map(MememberUserResponse::getPhone).collect(Collectors.toList());
        //判断触达方式
        String reachTypeList = map.getString("reachType");
        String[] reachType = reachTypeList.split(",");
        //执行动作记录-请求变量
        JSONObject reqVariable = new JSONObject();
        reqVariable.put("tripId",tripId);
        reqVariable.put("branchNodeId",branchNodeId);
        reqVariable.put("userIds",userIds);
        for(String type : reachType){
            //发送短信
            if(MessageTypeEnum.SMS_SEND.getCode().toString().equals(type)){
                JSONObject params = new JSONObject();
                String smsJson = map.getString("smsJson");
                params.put("params", JSONObject.parseObject(smsJson).get("params"));
                params.put("receiver",StringUtils.join(receiverSms,","));
                params.put("tempId",JSONObject.parseObject(smsJson).get("tempId"));
                params.put("accessKey",accessKey);

                log.info("发送短信, testSendSmsMailRequest: {}", JSONArray.toJSONString(params));
                HttpClientUtils.setHeader(new HashMap<String, String>(2){{
                    put("Content-Type","application/json;charset=UTF-8");
                }});
                String result = HttpClientUtils.doPostJson(smsUrl, params);
                messageResult.put("smsResult",result);
                log.info("调用短信结果, rest：{}",result);
                if(StringUtils.isNotEmpty(result)){
                    String code = JSONArray.parseObject(result, Map.class).get("code").toString();
                    if(SUCCESS_CODE.equals(code)){
                        flag = true;
                    }else{
                        log.error("调用短信失败,result："+result);
                        flag = false;
                    }
                }else{
                    log.error("调用短信失败,result：null");
                    flag = false;
                }
            }else if(MessageTypeEnum.MAIL_SEND.getCode().toString().equals(type)){
                JSONObject params = new JSONObject();
                String mailJson = map.getString("mailJson");
                params.put("params", JSONObject.parseObject(mailJson).get("params"));
                params.put("receiver",StringUtils.join(receiverMail,","));
                params.put("mailTitle",JSONObject.parseObject(mailJson).get("mailTitle"));
                params.put("tempId",JSONObject.parseObject(mailJson).get("tempId"));
                params.put("accessKey",accessKey);

                log.info("发送邮件, testSendSmsMailRequest: {}", JSONArray.toJSONString(params));
                HttpClientUtils.setHeader(new HashMap<String, String>(2){{
                    put("Content-Type","application/json;charset=UTF-8");
                }});
                String result = HttpClientUtils.doPostJson(mailUrl, params);
                messageResult.put("mailResult",result);
                log.info("调用邮件结果, rest：{}",result);
                if(StringUtils.isNotEmpty(result)){
                    String code = JSONArray.parseObject(result, Map.class).get("code").toString();
                    if(SUCCESS_CODE.equals(code)){
                        flag = true;
                    }else{
                        log.error("调用邮件失败,result："+result);
                        flag = false;
                    }
                }else{
                    log.error("调用邮件失败,result：null");
                    flag = false;
                }



            }
        }
        messageResult.put("receiverMail", receiverMail);
        messageResult.put("receiverSms", receiverSms);
        //插入执行记录表
        if(userIds.size() > 0 && (NodeTemplateTypeEnum.SEND_GOODS_NODE.getCode().equals(tripBranchNodeEntity.getNodeTemplateCode())
            || NodeTemplateTypeEnum.SEND_MARKET_NODE.getCode().equals(tripBranchNodeEntity.getNodeTemplateCode()))){
            foreachInsertTripExecuteInfo(reqVariable, userIds, tripBranchNodeEntity, flag, messageResult.toString());
        }
        // 下一个节点
        tripTimingJobService.exeNext(branchNodeId, userIds);
        return flag;
    }

    /**
     * 插入记录
     * @param reqVariable
     * @param userIds
     * @param tripBranchNodeEntity
     * @param flag
     * @param result
     * @return
     */
    private Long foreachInsertTripExecuteInfo(JSONObject reqVariable, List<String> userIds,
                                              TripBranchNodeEntity tripBranchNodeEntity, Boolean flag, String result){


        List<TripExecuteInfoEntity> tripExecuteInfoEntityList = new ArrayList<>();
        for(String userId : userIds){
            Boolean finalFlag = flag;
            TripExecuteInfoEntity tripExecuteInfoEntity = new TripExecuteInfoEntity(){{
                setThirdUserId(userId);
                setBranchId(tripBranchNodeEntity.getBranchId());
                setTripId(reqVariable.getLong("tripId"));
                setBranchNodeId(reqVariable.getLong("branchNodeId"));
                setNodeTemplateCode(tripBranchNodeEntity.getNodeTemplateCode());
                setRequestVariable(reqVariable.toString());
                setResponseVariable(result);
                setStatus(finalFlag == true ? 1 : 2);
                setType(1);
                setDeptId(tripBranchNodeEntity.getDeptId());
                setDeptType(tripBranchNodeEntity.getDeptType());

            }};
            tripExecuteInfoEntityList.add(tripExecuteInfoEntity);
        }
        return tripExecuteInfoEntityMapper.foreachInsert(tripExecuteInfoEntityList);
    }


    /**
     * 执行动作-推送商品
     * @param branchNodeId 分支节点ID
     * @return
     */
    @Override
    public Boolean branchNodeBySendGoods(Long tripId, Long branchNodeId, List<String> userIds){
        return branchNodeBySendMessage(tripId,branchNodeId,userIds);
    }

    /**
     * 校验短信设置
     * @return
     */
    private List<Long>  checkUserSendSmsCount(List<String> sendUserList){
        final  ImmutableMap<String, Integer> smsLimit = ImmutableMap.of("numberLimitDay",Integer.MAX_VALUE, "numberLimitWeek",Integer.MAX_VALUE, "numberLimitMonth", Integer.MAX_VALUE);
        List<TSmsTouchSettings> settings = tSmsTouchSettingsService.getSmsInfoByDeptId();
        for(TSmsTouchSettings setting : settings){
            if(TIME_LIMIT_DAY == setting.getTimeLimit()){
                smsLimit.put("numberLimitDay",setting.getNumberLimit() == null ? Integer.MAX_VALUE :setting.getNumberLimit());
            }else if(TIME_LIMIT_WEEK == setting.getTimeLimit()){
                smsLimit.put("numberLimitWeek",setting.getNumberLimit() == null ? Integer.MAX_VALUE :setting.getNumberLimit());
            }else if(TIME_LIMIT_MONTH == setting.getTimeLimit()){
                smsLimit.put("numberLimitMonth",setting.getNumberLimit() == null ? Integer.MAX_VALUE :setting.getNumberLimit());
            }
        }
        List<String> dayCount = tripExecuteInfoEntityMapper.getSendSmsByDay(StringUtils.join(sendUserList, ","))
                .stream().filter(x -> {
                    return x.getCnt() >= smsLimit.get("numberLimitDay");
                }).map(UserSendSmsCountResponse::getThirdUserId).collect(Collectors.toList());
        List<String> weekCount = tripExecuteInfoEntityMapper.getSendSmsByWeek(StringUtils.join(sendUserList,","))
                .stream().filter(x -> {
                    return x.getCnt() >= smsLimit.get("numberLimitWeek");
                }).map(UserSendSmsCountResponse::getThirdUserId).collect(Collectors.toList());
        List<String> monthCount = tripExecuteInfoEntityMapper.getSendSmsByMonth(StringUtils.join(sendUserList,","))
                .stream().filter(x -> {
                    return x.getCnt() >= smsLimit.get("numberLimitMonth");
                }).map(UserSendSmsCountResponse::getThirdUserId).collect(Collectors.toList());
        return  sendUserList
                .stream()
                .filter(x->{return !(dayCount.contains(x) || weekCount.contains(x) || monthCount.contains(x));})
                .map(Long::parseLong).collect(Collectors.toList());
    }


//    public static void main(String[] args) {
//        List<Long> user = new ArrayList<>();
//        user.add(1L);
//        user.add(2L);
//        user.add(3L);
//        System.out.println(StringUtils.join(user,","));
//    }
}